package com.atzly.community.controller.interceptor;

import com.atzly.community.entity.LoginTicket;
import com.atzly.community.entity.User;
import com.atzly.community.service.UserService;
import com.atzly.community.utils.CookieUtils;
import com.atzly.community.utils.HostHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;

/**   登录拦截请求器
 * @author zlysimida
 * @date 2021/8/27 - 13:23
 */
@Component
public class LoginInterceptor implements HandlerInterceptor {

    @Autowired
    private UserService userService;

    @Autowired
    private HostHolder hostHolder;

    // 在请求到达controller层之前处理
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 获取cookie中的用户登录凭证ticket
        String ticket = CookieUtils.getCookieTicket(request, "ticket");
        if(ticket != null) {
            // 查找凭证是否过期,或者不是活跃状态,或为空
            LoginTicket loginTicket = userService.selectTicketById(ticket);
            if(loginTicket != null && loginTicket.getTicket() != null && loginTicket.getStatus() == 0 && loginTicket.getExpired().after(new Date())){
                // 通过LoginTicket对象获得User对象
                User user = userService.selectById(loginTicket.getUserId());
                // 在多线程下保存User对象
                hostHolder.saveUserToThread(user);

                // (认证)构建用户认证的结果并存入securityContent,以便于security进行授权
                Authentication authentication = new UsernamePasswordAuthenticationToken(
                        user,user.getPassword(),userService.getAuthorities(user.getId())
                );
                // 将获取到的用户权限设置到securityContent对象中,用于后续的授权操作
                SecurityContextHolder.setContext(new SecurityContextImpl(authentication));
            }
        }
        return true;
    }

    // 在加载templateEngine之前处理向model中添加User对象
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        User user = hostHolder.getUserFromThread();
        if(user != null && modelAndView != null){
            modelAndView.addObject("loginUser",user);
        }
    }


    // 在加载templateEngine之后清除当前线程中的User对象防止内存泄漏
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        hostHolder.removeUserFromThread();
        // 当模板加载完成后清理securityContent中的authentication
//        SecurityContextHolder.clearContext();
    }
}
